package com.glsc.ngateway.platform.controller.system;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.util.CollectionUtils;
import com.github.pagehelper.util.StringUtil;
import com.glsc.ngateway.common.api.common.enums.Constant;
import com.glsc.ngateway.common.api.common.enums.DictConstant;
import com.glsc.ngateway.common.api.common.enums.PageConstant;
import com.glsc.ngateway.common.api.common.ex.Result;
import com.glsc.ngateway.common.api.flowable.dto.demand.FlowableAppendDto;
import com.glsc.ngateway.common.api.flowable.feign.IFeignFlowableService;
import com.glsc.ngateway.common.api.oaflow.dto.SystemFlowRelationResultDto;
import com.glsc.ngateway.common.api.oaflow.dto.SystemFlowStatisticsSearchParamDto;
import com.glsc.ngateway.common.api.oaflow.dto.param.ParamFlowSearchDto;
import com.glsc.ngateway.common.api.platform.dto.system.ParamSystemMainDto;
import com.glsc.ngateway.common.api.platform.dto.system.SystemMainDto;
import com.glsc.ngateway.common.api.platform.dto.user.PlatformUserDto;
import com.glsc.ngateway.common.api.platform.resp.PlatformResponse;
import com.glsc.ngateway.common.base.domain.mysql.gateway.system.SystemMain;
import com.glsc.ngateway.common.base.domain.mysql.gateway.system.SystemMainLog;
import com.glsc.ngateway.platform.aspect.UserCache;
import com.glsc.ngateway.platform.service.CommonService;
import com.glsc.ngateway.platform.service.UserService;
import com.glsc.ngateway.platform.service.owncloud.OwnCloudService;
import com.glsc.ngateway.platform.service.system.SystemMainService;
import com.glsc.ngateway.platform.utils.report.ExportFileEnum;
import com.glsc.ngateway.platform.vo.SystemFlowStatisticsVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


@RestController
@RequestMapping("/system/main")
@Api(value = "信息系统分类命名", tags = {"信息系统分类命名"})
public class SystemMainController {

    private static final Logger logger = LoggerFactory.getLogger(SystemMainController.class);
    @Autowired
    private SystemMainService systemMainService;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private UserCache userCache;
    @Autowired
    private UserService userService;
    @Resource
    private OwnCloudService ownCloudService;
    @Resource
    private IFeignFlowableService feignDemandService;
    @Resource
    CommonService commonService;

    /*
     * 新增或修改
     */
    @RequestMapping(method = RequestMethod.POST, value = "addOrUpdate")
    @ApiOperation(value = "新增或修改", notes = "新增或修改")
    public PlatformResponse<Void> addOrUpdate(@RequestBody SystemMain systemMain) {
        PlatformUserDto user = userCache.get(request);
        SystemMainService.SystemAddOrUpdateContext res = systemMainService.addOrUpdate(systemMain, user.getUsername());
//        try {
//            if (DictConstant.ADD.equals(res.getType())) {
//                ownCloudService.matchDir(List.of(res.getNewSystem().getOpName()), "【国联技术服务平台】由" + user.getName() + "新增");
//            } else if (DictConstant.UPDATE.equals(res.getType())) {
//                SystemMain oldSys = res.getOldSystem();
//                SystemMain newSys = res.getNewSystem();
//                //如果系统名称、系统大类、系统类别修改，则修改网盘系统文件名
//                //目前系统大类及系统类别在前端不能修改，这里暂时做兼容
//                if (!oldSys.getOpName().equals(newSys.getOpName()) || !oldSys.getMainClass().equals(newSys.getMainClass()) || !oldSys.getSystemClass().equals(newSys.getSystemClass())) {
//                    String comment = "【国联技术服务平台】由" + user.getName() + "修改，"
//                            + (!oldSys.getOpName().equals(newSys.getOpName()) ? oldSys.getOpName() + "->" + newSys.getOpName() : "");
//                    ownCloudService.renameSysDir(oldSys, newSys, comment);
//                }
//            }
//        } catch (Exception e) {
//            return PlatformResponse.successMsg("操作成功，网盘同步失败");
//        }
        return PlatformResponse.successMsg("创建或修改成功");
    }

    /**
     * 没有删除接口，只有下线
     */
//    @RequestMapping(method = RequestMethod.POST, value = "delete")
//    @ApiOperation(value = "删除", notes = "删除")
//    public Object delete(@RequestBody String param) throws Exception {
//        if (StringUtils.isEmpty(param)) {
//            return PlatformResponseNew.failedMsg("delete接口，参数为空。");
//        }
//        JSONObject jsonObject = (JSONObject) JSON.parse(param);
//        String id = jsonObject.getString("opId");
//        if (StringUtils.isNotEmpty(id)) {
//            systemMainService.delete(id);
//        }
//        return PlatformResponseNew.successData("删除成功");
//    }

    /**
     * 查询全部系统清单
     *
     * @return
     */
    @RequestMapping(method = RequestMethod.GET, value = "listAll")
    @ApiOperation(value = "查询全部系统清单", notes = "查询全部系统清单")
    public PlatformResponse<List<SystemMain>> queryAllSystemList() {
        List<SystemMain> result = systemMainService.queryAll();
        return PlatformResponse.successData(result);
    }

    @ApiOperation(value = "通过系统名称list查找系统", notes = "通过系统名称list查找系统")
    @RequestMapping(value = "/findAllBySystemIdIn", method = RequestMethod.GET)
    PlatformResponse<List<SystemMainDto>> findAllBySystemIdIn(@RequestParam("systemIdList") List<String> systemIdList) {
        return PlatformResponse.successData(systemMainService.findAllBySystemIdIn(systemIdList));
    }

    @RequestMapping("/getDocZip")
    @ApiOperation(value = "根据档案Ids批量下载zip文件", notes = "根据档案Ids批量下载zip文件")
    public Object getDocZip(@ApiParam(value = "zip文件名") @RequestParam(required = false) String zipFileName
            , HttpServletRequest request
            , HttpServletResponse response,
                            @RequestBody ParamSystemMainDto params) throws IOException {
        if (params.getPageNo() == null) {
            params.setPageNo(PageConstant.PageNo);
        }
        if (params.getPageSize() == null) {
            params.setPageSize(PageConstant.PageSize);
        }

        PlatformUserDto user = userCache.get(request);
        String account = user.getUsername();
        if (userService.userRoleContain(Constant.SYSTEM_ADMIN, account)) {
            account = null;
        }
        params.setMemberAccount(account);

        Page<SystemMain> result = systemMainService.search(params);
        List<String> docIdList = new ArrayList<>();
        result.getContent().stream().filter(e -> e.getSystemDoc() != null).forEach(m -> {
            String docIds = "";
            if ("doc".equalsIgnoreCase(params.getFileType())) {
                docIds = m.getSystemDoc().getDocIdList();
                if (StrUtil.isNotEmpty(docIds)) {
                    String[] docIdArr = docIds.split(",");
                    for (String docIdStr : docIdArr) {
                        docIdList.add(docIdStr);
                    }
                }
            } else {
                docIds = m.getSystemDoc().getPdfIdList();
                if (StrUtil.isNotEmpty(docIds)) {
                    String[] docIdArr = docIds.split(",");
                    for (String docIdStr : docIdArr) {
                        docIdList.add(docIdStr);
                    }
                }
            }

        });
        if (CollectionUtils.isEmpty(docIdList)) {
            return PlatformResponse.failedMsg("列表不存在或文件名为空");
        }

        logger.info("根据Ids批量下载zip文件,docIdList:" + docIdList);
        ResponseEntity<List<FlowableAppendDto>> appendInfos = feignDemandService.getAppendixInfos(docIdList);
        List<FlowableAppendDto> documentInfoList = appendInfos.getBody();

        if (CollectionUtils.isEmpty(documentInfoList)) {
            return PlatformResponse.failedMsg("档案列表不存在或文件名为空");
        }

        //设置压缩包的名字
        //解决不同浏览器压缩包名字含有中文时乱码的问题
        if (StrUtil.isEmpty(zipFileName)) {
            zipFileName = "系统清单附件.zip";
        }
        if (!zipFileName.endsWith(".zip")) {
            zipFileName = zipFileName + ".zip";
        }
        String userAgent = request.getHeader("User-Agent");
        // 针对IE或者以IE为内核的浏览器：
        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
            zipFileName = java.net.URLEncoder.encode(zipFileName, "UTF-8");
        } else {
            // 非IE浏览器的处理：
            zipFileName = new String(zipFileName.getBytes("UTF-8"), "ISO-8859-1");
        }
        response.setContentType("APPLICATION/OCTET-STREAM");
        response.setHeader("Content-Disposition", "attachment;filename=" + zipFileName);
        //设置压缩流：直接写入response，实现边压缩边下载
        ZipOutputStream zipos = null;
        try {
            zipos = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
            zipos.setMethod(ZipOutputStream.DEFLATED);//设置压缩方法
        } catch (Exception e) {
            logger.error("异常", e);
        }
        DataOutputStream os = null;
        //处理重名文件
        Map<String, Long> fileNameMap = documentInfoList.parallelStream().collect(Collectors.groupingBy(FlowableAppendDto::getAppendixName, Collectors.counting()));
        //循环将文件写入压缩流
        for (int i = 0; i < documentInfoList.size(); i++) {
            String filePath = documentInfoList.get(i).getAppendixPath();
            String fileName = documentInfoList.get(i).getAppendixName();
            File file = new File(filePath);//要下载文件的路径
            try {
                //添加ZipEntry，并ZipEntry中写入文件流
                //处理同名文件
                if (fileNameMap.get(fileName) > 1) {
                    fileName = commonService.reNameFileName(fileName, documentInfoList, i);
                }
                zipos.putNextEntry(new ZipEntry(fileName));
                os = new DataOutputStream(zipos);
                InputStream is = new FileInputStream(file);
                byte[] b = new byte[100];
                int length = 0;
                while ((length = is.read(b)) != -1) {
                    os.write(b, 0, length);
                }
                is.close();
                zipos.closeEntry();
            } catch (Exception e) {
                logger.error("根据档案Ids批量下载zip文件异常:", e);
            }
        }
        //关闭流
        try {
            os.flush();
            os.close();
            zipos.close();
        } catch (IOException e) {
            logger.error("根据档案Ids批量下载zip文件关闭流异常:", e);
            return null;
        }
        return null;
    }

    /**
     * 查询
     *
     * @param params
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "search")
    @ApiOperation(value = "查询", notes = "查询")
    public PlatformResponse<Page<SystemMain>> search(@RequestBody ParamSystemMainDto params) {
        if (params.getPageNo() == null) {
            params.setPageNo(PageConstant.PageNo);
        }
        if (params.getPageSize() == null) {
            params.setPageSize(PageConstant.PageSize);
        }

        PlatformUserDto user = userCache.get(request);
        String account = user.getUsername();
        if (userService.userRoleContain(Constant.SYSTEM_ADMIN, account)) {
            account = null;
        }
        params.setMemberAccount(account);

        Page<SystemMain> result = systemMainService.search(params);
        return PlatformResponse.successData(result);
    }

    @RequestMapping(method = RequestMethod.GET, value = "/findById")
    @ApiOperation(value = "根据id查询详情信息", notes = "根据id查询详情信息")
    public PlatformResponse<SystemMain> findByID(@RequestParam("opId") Integer opId) {
        return PlatformResponse.successData(systemMainService.findById(opId));
    }


    /**
     * 根据用户角色筛选用户可以查询的系统
     *
     * @param params
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "searchInvolved")
    @ApiOperation(value = "查询", notes = "查询")
    public PlatformResponse<Page<SystemMain>> searchInvolved(@RequestBody ParamSystemMainDto params) {
        if (params.getPageNo() == null) {
            params.setPageNo(PageConstant.PageNo);
        }
        if (params.getPageSize() == null) {
            params.setPageSize(PageConstant.PageSize);
        }

        PlatformUserDto user = userCache.get(request);
        String account = user.getUsername();
        Set<String> roleNames = new HashSet<>(user.getRoles());
        if (roleNames.contains("systemAdmin")) {
            account = null;
        }
        params.setMemberAccount(account);
        Page<SystemMain> result = systemMainService.search(params);
        return PlatformResponse.successData(result);
    }
//    /*
//     * 新增或修改
//     */
//    @RequestMapping(method = RequestMethod.POST, value = "advice")
//    @ApiOperation(value = "建议编号", notes = "建议编号")
//    public PlatformResponseNew advice(@RequestBody ParamSystemMainDto bean) {
//        String code = systemMainService.advice(bean);
//        PlatformResponseNew ret =  PlatformResponseNew.success();
//        ret.setData(code);
//        return ret;
//    }

    /*
     * 查看变更记录
     */
    @RequestMapping(method = RequestMethod.GET, value = "changeLog")
    @ApiOperation(value = "查看变更记录", notes = "查看变更记录")
    public PlatformResponse<List<SystemMainLog>> querySystemMainLog(Integer opId) {
        List<SystemMainLog> result = systemMainService.querySystemMainLog(opId);
        return PlatformResponse.successData(result);
    }

    /**
     * 根据登录人员查询其能看到的系统清单
     *
     * @return
     */
    @RequestMapping(method = RequestMethod.GET, value = "queryListByAuth")
    @ApiOperation(value = "查询全部系统清单", notes = "查询全部系统清单")
    public PlatformResponse<List<SystemMain>> queryListByAuth() {
        PlatformUserDto user = userCache.get(request);
        String account = user.getUsername();
        List<SystemMain> result = systemMainService.queryListByAuth(account);
        return PlatformResponse.successData(result);
    }

    /**
     *分页查询oa侧关联流程
     * @param systemClassNo
     * @return Page<VITSystemOAFlowResource>
     */
//    @RequestMapping(method = RequestMethod.GET, value = "getOaFlowList")
//    @ApiOperation(value = "查询oa侧关联流程", notes = "查询oa侧关联流程")
//    public PlatformResponse<PageDto<VITSystemOAFlowResource>> getOaFlowList(@RequestParam("systemClassNo") String systemClassNo,
//                                                                            @RequestParam("pageNo") Integer pageNo,
//                                                                            @RequestParam("pageSize") Integer pageSize
//                                                                         ) {
//        if (pageNo == null) {
//            pageNo = PageConstant.PageNo;
//        }
//        if (pageSize == null) {
//            pageSize = PageConstant.PageSize;
//        }
//        return PlatformResponse.successData(systemMainService.getOaFlowListBySystemClassNo(systemClassNo,pageNo,pageSize));
//    }

    /**
     * 不分页查询platform侧关联流程
     * @param systemClassNo
     * @return
     */
//    @RequestMapping(method = RequestMethod.GET, value = "getPlatformFlowList")
//    @ApiOperation(value = "查询platform侧关联流程", notes = "查询platform侧关联流程")
//    public PlatformResponse<HashMap<String,List<Object>>> getPlatformFlowList(String systemClassNo) {
//        return PlatformResponse.successData(systemMainService.getFlowListBySystemClassNo(systemClassNo));
//    }

    /**
     * 带条件查询oa和platform流程
     */
    @RequestMapping(method = RequestMethod.POST, value = "getFlowList")
    @ApiOperation(value = "查询系统关联流程", notes = "查询系统关联流程")
    public PlatformResponse<List<SystemFlowRelationResultDto>> getFlowList(@RequestBody ParamFlowSearchDto params) {
        if (StringUtil.isEmpty(params.getSystemClassNo())) {
            return PlatformResponse.failedMsg("系统编号不能为空！");
        }
        PlatformUserDto user = userCache.get(request);
        String account = user.getUsername();
        return PlatformResponse.successData(systemMainService.getFlowList(params, account));
    }

    /**
     * 带条件导出oa和platform流程
     */
    @RequestMapping(method = RequestMethod.POST, value = "exportSystemFlow")
    @ApiOperation(value = "导出系统关联流程", notes = "导出系统关联流程")
    public byte[] exportSystemFlow(@RequestBody ParamFlowSearchDto params, HttpServletResponse response) throws IOException {
        response.setHeader("Content-Disposition", "attachment;" + "filename=" + URLEncoder.encode(ExportFileEnum.SYSTEM_RELATION_FLOW.getFileName(), "UTF-8"));
        return systemMainService.exportSystemFlow(params);
    }

    /**
     * 系统关联流程统计
     *
     * @param params
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "statistics")
    @ApiOperation(value = "系统关联流程统计", notes = "系统关联流程统计")
    public PlatformResponse<SystemFlowStatisticsVo> systemFlowStatistics(@RequestBody SystemFlowStatisticsSearchParamDto params) throws Exception {
        PlatformUserDto user = userCache.get(request);
        String account = user.getUsername();
        return systemMainService.countSystemFlowStatistics(params, account);
    }
}